using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Org.BouncyCastle.Bcpg.OpenPgp;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Bcpg;
namespace Pbdms.Common.CryptoUtils
{
    public class Encrypter
    {
         //encrypt file
        public Boolean EncryptFile(string fileOut,string fileIn,PgpPublicKey encKey,bool withIntegrityCheck)
        {
            Stream outputStream;
            Stream outputStreamtemp = File.Create(fileOut);
            outputStream = new ArmoredOutputStream(outputStreamtemp);
            try
            {
                PgpEncryptedDataGenerator cPk = new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.Cast5, withIntegrityCheck, new SecureRandom());
                //Add a public key encrypted session key to the encrypted object.</
                cPk.AddMethod(encKey);

                Stream cOut = cPk.Open(outputStream, new byte[1 << 16]);

                PgpCompressedDataGenerator comData = new PgpCompressedDataGenerator(
                    CompressionAlgorithmTag.Zip);
                PgpUtilities.WriteFileToLiteralData(
                    comData.Open(cOut),
                    PgpLiteralData.Binary,
                    new FileInfo(fileIn),
                    new byte[1 << 16]);

                comData.Close();

                cOut.Close();
                outputStream.Close();
                outputStreamtemp.Close();
                return true;
            }
            catch (PgpException e)
            {
                //throw new Exception("encryption failed");
                return false;
            }
            finally
            {

                if (outputStream != null)
                {
                    outputStream.Close();
                }
                if (outputStreamtemp != null)
                {

                    outputStreamtemp.Close();
                }
            }
        }
        public string EncryptString(string randomString, PgpPublicKey encKey, bool withIntegrityCheck)
        {
            // set string to memory 
            MemoryStream inputMem = null;
            try
            {
                inputMem = new MemoryStream();
            }
            catch 
            {
                throw new Exception("unable to allocate memory");
            }
            System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
            try
            {
                byte[] data = encoding.GetBytes(randomString);
                int start = 0;

                while (start < data.Length)
                {
                    inputMem.WriteByte(data[start]);
                    start++;
                }

                inputMem.Seek(0, SeekOrigin.Begin);
            }
            catch (Exception ex)
            {
                inputMem.Close();
                throw new Exception("unable to convert to memory ");
            }
            MemoryStream outputMem = null;
            try
            {
                outputMem = new MemoryStream();
            }
            catch
            {
                throw new Exception("unable to allocate memory");
            }
            //Stream outStream = new ArmoredOutputStream(outMem);
            //Stream outs = new MemoryStream();
            Stream outStream = new ArmoredOutputStream(outputMem);
            PgpEncryptedDataGenerator cPk = new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.Cast5, withIntegrityCheck, new SecureRandom());
            if (encKey == null)
            {
                throw new Exception("no key");
            }
            cPk.AddMethod(encKey);
          
            Stream cOut = cPk.Open(outStream,new byte[1<<16]);
            PgpCompressedDataGenerator comData = new PgpCompressedDataGenerator(CompressionAlgorithmTag.Zip);
           
            PgpLiteralDataGenerator gen = new PgpLiteralDataGenerator();
            Stream lOut=gen.Open(comData.Open(cOut),PgpLiteralData.Binary,"Encrypt Message",inputMem.Length,DateTime.Now);
            int ch = 0;

            while ((ch = inputMem.ReadByte()) >= 0)
            {
                lOut.WriteByte((byte)ch);
            }
            lOut.Close();
            comData.Close();
            cOut.Close();
            outStream.Close();
            inputMem.Close();
         
            outputMem.Seek(0, SeekOrigin.Begin);

            int start2 = 0;
            byte[] newBytes2 = new byte[outputMem.Length];
            while (start2 < outputMem.Length)
            {
                newBytes2[start2] = (byte)outputMem.ReadByte();
                start2++;
            }
            System.Text.ASCIIEncoding encoder = new System.Text.ASCIIEncoding();
            string str = encoder.GetString(newBytes2);
            outputMem.Close();
            return str;
            
          
            


        }

        public MemoryStream EncryptBytes(MemoryStream bytesToEncrypt, PgpPublicKey encKey, bool withIntegrityCheck)
        {
            // set string to memory 
           
            MemoryStream outputMem = null;
            try
            {
                outputMem = new MemoryStream();
            }
            catch
            {
                throw new Exception("unable to allocate memory");
            }
            //Stream outStream = new ArmoredOutputStream(outMem);
            //Stream outs = new MemoryStream();
            Stream outStream = new ArmoredOutputStream(outputMem);
            PgpEncryptedDataGenerator cPk = new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.Cast5, withIntegrityCheck, new SecureRandom());
            if (encKey == null)
            {
                return null;
            }
            cPk.AddMethod(encKey);

            Stream cOut = cPk.Open(outStream, new byte[1 << 16]);
            PgpCompressedDataGenerator comData = new PgpCompressedDataGenerator(CompressionAlgorithmTag.Zip);

            PgpLiteralDataGenerator gen = new PgpLiteralDataGenerator();
            Stream lOut = gen.Open(comData.Open(cOut), PgpLiteralData.Binary, "Encrypt Message", bytesToEncrypt.Length, DateTime.Now);
            int ch = 0;

            while ((ch = bytesToEncrypt.ReadByte()) >= 0)
            {
                lOut.WriteByte((byte)ch);
            }
            lOut.Close();
            comData.Close();
            cOut.Close();
            outStream.Close();
            bytesToEncrypt.Close();

            outputMem.Seek(0, SeekOrigin.Begin);

            return outputMem;
        }
    }
}
